; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+avx512fp16 < %s | FileCheck %s

; Test cases derived from float/double tests in fp-logic.ll

; 1 FP operand, 1 int operand, int result

define i16 @f1(half %x, i16 %y) {
; CHECK-LABEL: f1:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovw %xmm0, %eax
; CHECK-NEXT:    andl %edi, %eax
; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %bc1, %y
  ret i16 %and
}

; Swap operands of the logic op.

define i16 @f2(half %x, i16 %y) {
; CHECK-LABEL: f2:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovw %xmm0, %eax
; CHECK-NEXT:    andl %edi, %eax
; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %y, %bc1
  ret i16 %and
}

; 1 FP operand, 1 constant operand, int result

define i16 @f3(half %x) {
; CHECK-LABEL: f3:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovw %xmm0, %eax
; CHECK-NEXT:    andl $1, %eax
; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %bc1, 1
  ret i16 %and
}

; Swap operands of the logic op.

define i16 @f4(half %x) {
; CHECK-LABEL: f4:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovw %xmm0, %eax
; CHECK-NEXT:    andl $2, %eax
; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 2, %bc1
  ret i16 %and
}

; 1 FP operand, 1 integer operand, FP result

define half @f5(half %x, i16 %y) {
; CHECK-LABEL: f5:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovw %edi, %xmm1
; CHECK-NEXT:    vandps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %bc1, %y
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

; Swap operands of the logic op.

define half @f6(half %x, i16 %y) {
; CHECK-LABEL: f6:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovw %edi, %xmm1
; CHECK-NEXT:    vandps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %y, %bc1
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

; 1 FP operand, 1 constant operand, FP result

define half @f7(half %x) {
; CHECK-LABEL: f7:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovsh {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT:    vandps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %bc1, 3
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

; Swap operands of the logic op.

define half @f8(half %x) {
; CHECK-LABEL: f8:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovsh {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT:    vandps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 4, %bc1
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

; 2 FP operands, int result

define i16 @f9(half %x, half %y) {
; CHECK-LABEL: f9:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vandps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    vmovw %xmm0, %eax
; CHECK-NEXT:    # kill: def $ax killed $ax killed $eax
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %bc2 = bitcast half %y to i16
  %and = and i16 %bc1, %bc2
  ret i16 %and
}

; 2 FP operands, FP result

define half @f10(half %x, half %y) {
; CHECK-LABEL: f10:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vandps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %bc2 = bitcast half %y to i16
  %and = and i16 %bc1, %bc2
  %bc3 = bitcast i16 %and to half
  ret half %bc3
}

define half @or(half %x, half %y) {
; CHECK-LABEL: or:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vorps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %bc2 = bitcast half %y to i16
  %and = or i16 %bc1, %bc2
  %bc3 = bitcast i16 %and to half
  ret half %bc3
}

define half @xor(half %x, half %y) {
; CHECK-LABEL: xor:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vxorps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %bc2 = bitcast half %y to i16
  %and = xor i16 %bc1, %bc2
  %bc3 = bitcast i16 %and to half
  ret half %bc3
}

define half @f7_or(half %x) {
; CHECK-LABEL: f7_or:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovsh {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT:    vorps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = or i16 %bc1, 3
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

define half @f7_xor(half %x) {
; CHECK-LABEL: f7_xor:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovsh {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT:    vxorps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = xor i16 %bc1, 3
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

; Grabbing the sign bit is a special case that could be handled
; by movmskps/movmskpd, but if we're not shifting it over, then
; a simple FP logic op is cheaper.

define half @movmsk(half %x) {
; CHECK-LABEL: movmsk:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovsh {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
; CHECK-NEXT:    vandps %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %bc1, 32768
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

define half @bitcast_fabs(half %x) {
; CHECK-LABEL: bitcast_fabs:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vpbroadcastw {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN]
; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %and = and i16 %bc1, 32767
  %bc2 = bitcast i16 %and to half
  ret half %bc2
}

define half @bitcast_fneg(half %x) {
; CHECK-LABEL: bitcast_fneg:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vpbroadcastw {{.*#+}} xmm1 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %x to i16
  %xor = xor i16 %bc1, 32768
  %bc2 = bitcast i16 %xor to half
  ret half %bc2
}

define <8 x half> @bitcast_fabs_vec(<8 x half> %x) {
; CHECK-LABEL: bitcast_fabs_vec:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vpbroadcastw {{.*#+}} xmm1 = [NaN,NaN,NaN,NaN,NaN,NaN,NaN,NaN]
; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %x to <8 x i16>
  %and = and <8 x i16> %bc1, <i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767, i16 32767>
  %bc2 = bitcast <8 x i16> %and to <8 x half>
  ret <8 x half> %bc2
}

define <8 x half> @bitcast_fneg_vec(<8 x half> %x) {
; CHECK-LABEL: bitcast_fneg_vec:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vpbroadcastw {{.*#+}} xmm1 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
; CHECK-NEXT:    vpxor %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %x to <8 x i16>
  %xor = xor <8 x i16> %bc1, <i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768>
  %bc2 = bitcast <8 x i16> %xor to <8 x half>
  ret <8 x half> %bc2
}

define half @fadd_bitcast_fneg(half %x, half %y) {
; CHECK-LABEL: fadd_bitcast_fneg:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsubsh %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %y to i16
  %xor = xor i16 %bc1, 32768
  %bc2 = bitcast i16 %xor to half
  %fadd = fadd half %x, %bc2
  ret half %fadd
}

define half @fsub_bitcast_fneg(half %x, half %y) {
; CHECK-LABEL: fsub_bitcast_fneg:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vmovsh {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm2
; CHECK-NEXT:    vxorps %xmm2, %xmm1, %xmm1
; CHECK-NEXT:    vsubsh %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast half %y to i16
  %xor = xor i16 %bc1, 32767
  %bc2 = bitcast i16 %xor to half
  %fsub = fsub half %x, %bc2
  ret half %fsub
}

define half @nabs(half %a) {
; CHECK-LABEL: nabs:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vpbroadcastw {{.*#+}} xmm1 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
; CHECK-NEXT:    vpor %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %conv = bitcast half %a to i16
  %and = or i16 %conv, -32768
  %conv1 = bitcast i16 %and to half
  ret half %conv1
}

define <8 x half> @nabsv8f16(<8 x half> %a) {
; CHECK-LABEL: nabsv8f16:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vpbroadcastw {{.*#+}} xmm1 = [-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0,-0.0E+0]
; CHECK-NEXT:    vpor %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %conv = bitcast <8 x half> %a to <8 x i16>
  %and = or <8 x i16> %conv, <i16 -32768, i16 -32768, i16 -32768, i16 -32768, i16 -32768, i16 -32768, i16 -32768, i16 -32768>
  %conv1 = bitcast <8 x i16> %and to <8 x half>
  ret <8 x half> %conv1
}

define <8 x half> @fadd_bitcast_fneg_vec(<8 x half> %x, <8 x half> %y) {
; CHECK-LABEL: fadd_bitcast_fneg_vec:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsubph %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %y to <8 x i16>
  %xor = xor <8 x i16> %bc1, <i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768>
  %bc2 = bitcast <8 x i16> %xor to <8 x half>
  %fadd = fadd <8 x half> %x, %bc2
  ret <8 x half> %fadd
}

define <8 x half> @fadd_bitcast_fneg_vec_undef_elts(<8 x half> %x, <8 x half> %y) {
; CHECK-LABEL: fadd_bitcast_fneg_vec_undef_elts:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vsubph %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %y to <8 x i16>
  %xor = xor <8 x i16> %bc1, <i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 undef, i16 32768>
  %bc2 = bitcast <8 x i16> %xor to <8 x half>
  %fadd = fadd <8 x half> %x, %bc2
  ret <8 x half> %fadd
}

define <8 x half> @fsub_bitcast_fneg_vec(<8 x half> %x, <8 x half> %y) {
; CHECK-LABEL: fsub_bitcast_fneg_vec:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vaddph %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %y to <8 x i16>
  %xor = xor <8 x i16> %bc1, <i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768>
  %bc2 = bitcast <8 x i16> %xor to <8 x half>
  %fsub = fsub <8 x half> %x, %bc2
  ret <8 x half> %fsub
}

define <8 x half> @fsub_bitcast_fneg_vec_undef_elts(<8 x half> %x, <8 x half> %y) {
; CHECK-LABEL: fsub_bitcast_fneg_vec_undef_elts:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vaddph %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %y to <8 x i16>
  %xor = xor <8 x i16> %bc1, <i16 undef, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 32768, i16 undef>
  %bc2 = bitcast <8 x i16> %xor to <8 x half>
  %fsub = fsub <8 x half> %x, %bc2
  ret <8 x half> %fsub
}

define <8 x half> @fadd_bitcast_fneg_vec_width(<8 x half> %x, <8 x half> %y) {
; CHECK-LABEL: fadd_bitcast_fneg_vec_width:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vxorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1
; CHECK-NEXT:    vaddph %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %y to <2 x i64>
  %xor = xor <2 x i64> %bc1, <i64 -9223231297218904064, i64 -9223231297218904064>
  %bc2 = bitcast <2 x i64> %xor to <8 x half>
  %fadd = fadd <8 x half> %x, %bc2
  ret <8 x half> %fadd
}

define <8 x half> @fsub_bitcast_fneg_vec_width(<8 x half> %x, <8 x half> %y) {
; CHECK-LABEL: fsub_bitcast_fneg_vec_width:
; CHECK:       # %bb.0:
; CHECK-NEXT:    vxorps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1, %xmm1
; CHECK-NEXT:    vsubph %xmm1, %xmm0, %xmm0
; CHECK-NEXT:    retq
  %bc1 = bitcast <8 x half> %y to <2 x i64>
  %xor = xor <2 x i64> %bc1, <i64 -9223231297218904064, i64 -9223231297218904064>
  %bc2 = bitcast <2 x i64> %xor to <8 x half>
  %fsub = fsub <8 x half> %x, %bc2
  ret <8 x half> %fsub
}
